﻿import { Controller } from 'egg';
import * as bcrypt from 'bcryptjs';
import * as jwt from 'jsonwebtoken';
import { ethers } from 'ethers';

// 简单校验 helpers（避免新增外部依赖）
function isValidEmail(email: string) {
  return typeof email === 'string' && /^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(email);
}

function isValidWallet(address: string) {
  return typeof address === 'string' && /^0x[a-fA-F0-9]{40}$/.test(address);
}

class AuthController extends Controller {
  // 用户注册
  public async register() {
    const { ctx } = this;
    let { name, email, password, role = 'user' } = ctx.request.body;

    // 规范化输入
    email = typeof email === 'string' ? email.trim().toLowerCase() : email;

    try {
      // 验证输入
      if (!name || !email || !password) {
        ctx.status = 400;
        ctx.body = { success: false, message: '请填写完整信息' };
        return;
      }

      if (!isValidEmail(email)) {
        ctx.status = 400; 
        ctx.body = { success: false, message: '邮箱格式不正确' };
        return;
      }

      if (typeof password !== 'string' || password.length < 6) {
        ctx.status = 400;
        ctx.body = { success: false, message: '密码长度至少 6 位' };
        return;
      }

      // 检查邮箱是否已存在
      const existingUser = await ctx.model.User.findOne({ where: { email } });
      if (existingUser) {
        ctx.status = 400;
        ctx.body = { success: false, message: '邮箱已被注册' };
        return;
      }

      // 加密密码
      const hashedPassword = await bcrypt.hash(password, 10);

      // 创建用户
      let user;
      try {
        user = await ctx.model.User.create({
          name,
          email,
          password: hashedPassword,
          role
        });
      } catch (err: any) {
        // 捕获数据库唯一约束等错误
        if (err && (
          err.name === 'SequelizeUniqueConstraintError' || 
          (err.original && err.original.code === 'ER_DUP_ENTRY')
        )) {
          ctx.status = 400;
          ctx.body = { success: false, message: '邮箱已被注册' };
          return;
        }
        throw err;
      }

      // 生成JWT token
      const jwtSecret = (ctx.app.config && ctx.app.config.jwt && ctx.app.config.jwt.secret) || process.env.JWT_SECRET;
      if (!jwtSecret || typeof jwtSecret !== 'string') {
        ctx.logger.error('JWT secret is not configured');
        ctx.status = 500;
        ctx.body = { success: false, message: '服务器配置错误' };
        return;
      }

      const token = jwt.sign(
        { userId: user.id, email: user.email },
        jwtSecret as string,
        { expiresIn: '7d' }
      );

      ctx.body = {
        success: true,
        message: '注册成功',
        data: {
          user: {
            id: user.id,
            name: user.name,
            email: user.email,
            role: user.role
          },
          token
        }
      };
    } catch (error) {
      ctx.logger.error('注册失败:', error);
      ctx.status = 500;
      ctx.body = { success: false, message: '注册失败，请稍后重试' };
    }
  }

  // 用户登录
  public async login() {
    const { ctx } = this;
    let { email, password } = ctx.request.body;
    email = typeof email === 'string' ? email.trim().toLowerCase() : email;

    try {
      // 验证输入
      if (!email || !password) {
        ctx.status = 400;
        ctx.body = { success: false, message: '请填写邮箱和密码' };
        return;
      }

      if (!isValidEmail(email)) {
        ctx.status = 400;
        ctx.body = { success: false, message: '邮箱格式不正确' };
        return;
      }

      // 查找用户
      const user = await ctx.model.User.findOne({ where: { email } });
      if (!user) {
        ctx.status = 401;
        ctx.body = { success: false, message: '邮箱或密码错误' };
        return;
      }

      // 验证密码
      const isValidPassword = await bcrypt.compare(password, user.password);
      if (!isValidPassword) {
        ctx.status = 401;
        ctx.body = { success: false, message: '邮箱或密码错误' };
        return;
      }

      // 检查账户状态
      if (user.status !== 'active') {
        ctx.status = 401;
        ctx.body = { success: false, message: '账户已被禁用' };
        return;
      }

      // 更新最后登录时间
      await user.update({ lastLoginAt: new Date() });

      // 生成JWT token
      const jwtSecret = (ctx.app.config && ctx.app.config.jwt && ctx.app.config.jwt.secret) || process.env.JWT_SECRET;
      if (!jwtSecret || typeof jwtSecret !== 'string') {
        ctx.logger.error('JWT secret is not configured');
        ctx.status = 500;
        ctx.body = { success: false, message: '服务器配置错误' };
        return;
      }

      const token = jwt.sign(
        { userId: user.id, email: user.email },
        jwtSecret as string,
        { expiresIn: '7d' }
      );

      ctx.body = {
        success: true,
        message: '登录成功',
        data: {
          user: {
            id: user.id,
            name: user.name,
            email: user.email,
            role: user.role,
            walletAddress: user.wallet_address
          },
          token
        }
      };
    } catch (error) {
      ctx.logger.error('登录失败:', error);
      ctx.status = 500;
      ctx.body = { success: false, message: '登录失败，请稍后重试' };
    }
  }

  // 获取当前用户信息
  public async profile() {
    const { ctx } = this;

    try {
      const userId = ctx.state.user.userId;
      const user = await ctx.model.User.findByPk(userId, {
        attributes: { exclude: ['password'] },
        include: [
          {
            model: ctx.model.Project,
            as: 'projects',
            separate: true, // 确保 limit 在关联中生效
            limit: 5,
            order: [['createdAt', 'DESC']]
          }
        ]
      });

      if (!user) {
        ctx.status = 404;
        ctx.body = { success: false, message: '用户不存在' };
        return;
      }

      ctx.body = {
        success: true,
        data: user
      };
    } catch (error) {
      ctx.logger.error('获取用户信息失败:', error);
      ctx.status = 500;
      ctx.body = { success: false, message: '获取用户信息失败' };
    }
  }

  // 更新用户信息
  public async updateProfile() {
    const { ctx } = this;
    const { name, bio, phone, avatar } = ctx.request.body;

    try {
      const userId = ctx.state.user.userId;
      const user = await ctx.model.User.findByPk(userId);

      if (!user) {
        ctx.status = 404;
        ctx.body = { success: false, message: '用户不存在' };
        return;
      }

      await user.update({
        name: name || user.name,
        bio: bio || user.bio,
        phone: phone || user.phone,
        avatar: avatar || user.avatar
      });

      ctx.body = {
        success: true,
        message: '更新成功',
        data: {
          id: user.id,
          name: user.name,
          email: user.email,
          bio: user.bio,
          phone: user.phone,
          avatar: user.avatar
        }
      };
    } catch (error) {
      ctx.logger.error('更新用户信息失败:', error);
      ctx.status = 500;
      ctx.body = { success: false, message: '更新失败，请稍后重试' };
    }
  }

  // 生成钱包连接 nonce
  public async walletNonce() {
    const { ctx } = this;
    try {
      const userId = ctx.state.user.userId;
      const user = await ctx.model.User.findByPk(userId);
      if (!user) {
        ctx.status = 404;
        ctx.body = { success: false, message: '用户不存在' };
        return;
      }

      // 生成随机 nonce 并存储到 session
      const nonce = `Sign this message to verify you own this wallet. Nonce: ${Math.random().toString(36).substring(2)}`;
      ctx.session.walletNonce = nonce;
      ctx.session.walletNonceUserId = userId;  // 记录请求 nonce 的用户 ID

      ctx.body = {
        success: true,
        data: { nonce }
      };
    } catch (error) {
      ctx.logger.error('生成 nonce 失败:', error);
      ctx.status = 500;
      ctx.body = { success: false, message: '生成验证消息失败，请稍后重试' };
    }
  }

  // 验证钱包签名并绑定
  public async verifyWallet() {
    const { ctx } = this;
    const { address, signature, message } = ctx.request.body;

    try {
      // 基本输入验证
      if (!address || !signature || !message) {
        ctx.status = 400;
        ctx.body = { success: false, message: '请提供完整的钱包验证信息' };
        return;
      }

      const userId = ctx.state.user.userId;
      const user = await ctx.model.User.findByPk(userId);
      if (!user) {
        ctx.status = 404;
        ctx.body = { success: false, message: '用户不存在' };
        return;
      }

      // 验证 nonce
      const savedNonce = ctx.session.walletNonce;
      const savedUserId = ctx.session.walletNonceUserId;

      if (!savedNonce || !savedUserId || savedUserId !== userId || savedNonce !== message) {
        ctx.status = 400;
        ctx.body = { success: false, message: '验证消息无效或已过期' };
        return;
      }

      // 规范化地址
      let normalizedAddress: string;
      try {
        normalizedAddress = ethers.utils.getAddress(address);
      } catch (e) {
        ctx.status = 400;
        ctx.body = { success: false, message: '钱包地址格式不正确' };
        return;
      }

      // 验证签名
      try {
        const recoveredAddress = ethers.utils.verifyMessage(message, signature);
        if (normalizedAddress.toLowerCase() !== recoveredAddress.toLowerCase()) {
          ctx.status = 400;
          ctx.body = { success: false, message: '签名验证失败' };
          return;
        }
      } catch (e) {
        ctx.status = 400;
        ctx.body = { success: false, message: '签名格式不正确' };
        return;
      }

      // 检查钱包地址是否已被其他用户使用
      const existingUser = await ctx.model.User.findOne({
        where: { wallet_address: normalizedAddress }
      });

      if (existingUser && String(existingUser.id) !== String(userId)) {
        ctx.status = 400;
        ctx.body = { success: false, message: '该钱包地址已被其他用户绑定' };
        return;
      }

      // 如果当前用户已绑定这个地址，直接返回成功
      if (user.wallet_address === normalizedAddress) {
        ctx.body = {
          success: true,
          message: '钱包已绑定',
          data: { walletAddress: normalizedAddress }
        };
        // 清除 session 中的 nonce
        delete ctx.session.walletNonce;
        delete ctx.session.walletNonceUserId;
        return;
      }

      // 更新用户钱包地址
      try {
        const updated = await user.update({ wallet_address: normalizedAddress });
        // 清除 session 中的 nonce
        delete ctx.session.walletNonce;
        delete ctx.session.walletNonceUserId;

        ctx.body = {
          success: true,
          message: '钱包绑定成功',
          data: { walletAddress: updated.wallet_address }
        };
      } catch (err: any) {
        // 处理唯一约束错误
        if (err.name === 'SequelizeUniqueConstraintError' ||
            (err.original && err.original.code === 'ER_DUP_ENTRY')) {
          ctx.status = 400;
          ctx.body = { success: false, message: '该钱包地址已被其他用户绑定' };
          return;
        }
        throw err;
      }
    } catch (error) {
      ctx.logger.error('验证钱包失败:', error);
      ctx.status = 500;
      ctx.body = { success: false, message: '验证钱包失败，请稍后重试' };
    }
  }
}

export default AuthController;